/**
 * Por Miguel Salas
 * Arbol generico 
 * @class Extmx.tree.TreeExplorer
 * Arbol generico para crear un arbol
 *
 * @extends Ext.tree.TreePanel
 * @autor Ing. Miguel Salas
 *        miguelsalasmx@gmail.com<br>
 * @fecha 3 de febrero de 2011. Mexico DF
 *
 */

Ext.ns("Extmx.tree.TreeExplorer");

Extmx.tree.TreeExplorer = Ext.extend(Ext.tree.TreePanel,{
    width:240,
    useArrows: true,
    header :false,
    collapseMode: 'mini',
    collapsible: true,
    minWidth: 150,
    maxWidth: 350,
    split:true,
    autoScroll: true,
    animate: true,
    containerScroll: true,
    border: false,
    enableDD: true,
    ddAppendOnly:true,

    /**
     * @cfg String dataUrl Debe definir la ruta que lista las carpetas
     */

    initComponent:function(){        
        Ext.apply(this,this.getRootConfig());

        Extmx.tree.TreeExplorer.superclass.initComponent.call(this);

        //Editor de texto de los nodos
        this.treeE=new Ext.tree.TreeEditor(this, new Ext.form.TextField({
            allowBlank: false,
            blankText: 'Escriba el nombre de la carpeta por favor',
            vtype:"nombre",
            maxLength:100
        }), {
            allowBlur:false,
            selectOnFocus:true
        });

        this.relayEvents(this.treeE,["beforecomplete", "cancelEdit", "complete" ]);
        this.addEvents("error");

        //this.addEvents('actualizarorganigrama');
        this.loader.on('load',function(){            
            this.root.select();
        },this);

        this.on({
            scope:this,
            beforecomplete : this.onBeforeComplete,
            cancelEdit: this.onCancelEdit,
            complete: this.onComplete,
            nodedrop : this.onNodeDrop,
            beforenodedrop : this.beforeNodeDrop,
            click: this.onNodeClick, 
            contextmenu: function(node, e) {
            //Registrar el contxto dl nodo con el menu
            //de esa manera la funcion controlador del Menu pueda acceder a el
            //por medio de su propiedad parentMenu
                node.select();
                
                var c = node.getOwnerTree().contextMenu;
                c.contextNode = node;
                c.items.items[1].setDisabled(false);
                c.items.items[2].setDisabled(false);
                if(node.id=="0"){
                    c.items.items[1].setDisabled(true);
                    c.items.items[2].setDisabled(true);
                }
                c.showAt(e.getXY());
            }
        });
    },
    getRootConfig: function(){
        var config_ini = {
            root: {
                nodeType: 'async',
                text: '/',
                iconCls:"application_home",
                draggable: false,
                editable:false,
                animate:false,
                id: '0',
                carpeta_k:'0',
                expanded :false
            },
            contextMenu: new Ext.menu.Menu({
                    items: this.getContextMenu()
                })
        };
        return config_ini;
    },
    /**
     * Retorna el menu (Array) a desplegar cuando se de click derecho con el mouse
     * @method getContextMenu
     * @return {Array} menu
     */
    getContextMenu: function (){
            return [];
    },

    /**
     * Funcion templete que define la accion y el codigo a ejecutar de acuerdo a la opcion de menu seleccionada
     * en el contextMenu. Esta funcion debe ser sobre escrita si cambia se sobreescribe el menu
     * @method nodoPresionado
     * @param {opcionmenu} menu Opcion del menu presionado
     * @param {Evento} evento
     * @param {Comando} coamndo de accion a ejecutar
     */
    nodoPresionado: Ext.emptyFn,
    

    startNodoEdit: function (nodo){
        this.treeE.editNode=nodo;
        this.treeE.startEdit(nodo.ui.textNode);
    },

    agregarNodo: function (item){
        var p=this;
        //expandir el nodo antes de meterle 1
        item.expand(false,true,function (){
            var node = item.appendChild(new Ext.tree.TreeNode({
                text:'',
                iconCls:'folder'//,
                //allowDrag:false
            }));
            //log(node);
            //seleccionar el recien insertado
            

            //editarlo
            setTimeout(function(){
                node.select();
                p.treeE.editNode=node;
                p.treeE.startEdit(node.ui.textNode);
            },500);
        },true);
    },
    eliminarNodo: Ext.emptyFn,
    existeCarpeta: function(nombre){
        var padre;
        padre=this.getPadreSeleccionado();
        var nodos=padre.childNodes;
        for (var hijo=0; hijo<nodos.length; hijo++)
            if(nodos[hijo].attributes.text == nombre&&nodos[hijo].attributes.id!=id)
                return true;
        return false;
    },

    onBeforeComplete: function (Editor_this, Mixed_value, Mixed_startValue ){
        if(Mixed_value!=Mixed_startValue){
            if(this.existeCarpeta(Mixed_value,Mixed_startValue)){
            //si ya existe una carpeta con ese nombre
                this.fireEvent("error","Ya existe una carpeta con ese nombre, escriba otro por favor",this);
                return false;
            }
        }
    },

    onCancelEdit: function(Editor_this, Mixed_value, Mixed_startValue){
        if(Mixed_startValue<1){
        //si cancela sin tener contenido
            //this.getSelectionModel().select(this.getPadreSeleccionado());
            this.getSeleccionado().remove();
        }
    },

    /**
     * Esta funcion debe ser sobreescrita para ejecutar alguna implemetacion al terminar de editar
     * @method onComplete
     * @param {Editor} editor Editor de texto del nodo
     * @param {Mixed} value Nuevo valor
     * @param {Mixed} startValue Valor inicial
     */
    onComplete: Ext.emptyFn,

    /**
     * Retorna el nodo seleccionado
     * @method getSeleccionado
     * @return Nodo seleccioado
     */
    getSeleccionado: function (){
        return this.getSelectionModel().getSelectedNode();
    },

    /**
     * Retorna el padre del nodo seleccionado
     * @method getPadreSeleccionado
     * @return nodo padre del nodo seleccionado
     */
    getPadreSeleccionado: function (){
        return this.getSelectionModel().getSelectedNode().parentNode;
    },

     /**
     * @method nodedragover
     * @para {Object} objeto
     * Fires when a tree node is being targeted for a drag drop, return false
     * to signal drop not allowed. The dragOverEvent
     * passed to handlers has the following properties:
     *
     * tree - The TreePanel
     * target - The node being targeted for the drop
     * data - The drag data from the drag source
     */
    onNodeDrop: Ext.emptyFn,


    /**
     * @event beforeNodeDrop
     * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent
     * passed to handlers has the following properties:
     *
     * tree - The TreePanel
     * target - The node being targeted for the drop
     * data - The drag data from the drag source
     * point - The point of the drop - append, above or below
     * source - The drag source
     * rawEvent - Raw mouse event
     * dropNode - Drop node(s) provided by the source OR you can supply node(s)
     * to be inserted by setting them on this object.
     * cancel - Set this to true to cancel the drop.
     * dropStatus - If the default drop action is cancelled but the drop is valid, setting this to true
     * will prevent the animated 'repair' from appearing.
     *
     * @param {Object} dropEvent
     */
    beforeNodeDrop: Ext.emptyFn,


    /**
     * Esta funcion es ejecutada al presionar un nodo del arbol
     * @method onNodeClick
     */
    onNodeClick: Ext.emptyFn,
    existeCarpetaDrop:function(target,nombre){
        var nodos=target.childNodes;
        for (var hijo=0; hijo<nodos.length; hijo++)
            if(nodos[hijo].attributes.text == nombre)
                return true;
        return false;
    },
    getTargetDrop:function(Object_dropEvent){
        return Object_dropEvent.target;
    },
    getNodeDrop:function(Object_dropEvent){
        return Object_dropEvent.dropNode;
    }
});